home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part13 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  30.9 KB

  1. Subject:  v18i035:  Mail user's shell version 6.4, Part13/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 35
  8. Archive-name: mush6.4/part13
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 13 (of 19)."
  19. # Contents:  commands.c
  20. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:19 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'commands.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'commands.c'\"
  24. else
  25. echo shar: Extracting \"'commands.c'\" \(29012 characters\)
  26. sed "s/^X//" >'commands.c' <<'END_OF_FILE'
  27. X/* @(#)commands.c    (c) copyright 10/18/86 (Dan Heller) */
  28. X
  29. X#include "mush.h"
  30. X
  31. X/*
  32. X * Note that all of the routines in here act upon and return 0 or -1.
  33. X * if -1, then the main loop will clear message lists.
  34. X */
  35. X
  36. Xstruct cmd cmds[] = {
  37. X#ifdef SIGSTOP
  38. X    { "stop", stop },
  39. X#endif /* SIGSTOP */
  40. X    { "?",       question_mark },{ "sh", sh },
  41. X    { "alias",       do_alias    },  { "unalias",    do_alias   },
  42. X    { "expand",      do_alias    },  { "cmd",     do_alias   },
  43. X    { "uncmd",       do_alias    },  { "from",    do_from    },
  44. X    { "un_hdr",      do_alias    },  { "my_hdr",      do_alias   },
  45. X    { "fkey",       do_alias    },  { "unfkey",     do_alias   },
  46. X    { "set",       set         },  { "unset",     set        },
  47. X    { "ignore",      set         },  { "unignore", set        },
  48. X    { "version",  do_version  },  { "help",    print_help },
  49. X    { "pick",       do_pick     },  { "sort",     sort        },
  50. X    { "next",      readmsg     },  { "previous", readmsg    },
  51. X    { "type",     readmsg     },  { "print",    readmsg    },
  52. X    { "history",  disp_hist   },  { "top",    readmsg       },
  53. X    { "saveopts", save_opts   },  { "source",   source        },
  54. X    { "headers",  do_hdrs     },  { "ls",    ls       },
  55. X    { "folder",   folder      },  { "update",   folder     },
  56. X    { "cd",       cd          },  { "pwd",    cd        },
  57. X    { "exit",      quit        },  { "quit",     quit        },
  58. X    { "write",       save_msg    },  { "save",     save_msg   },
  59. X    { "copy",       save_msg    },  { "folders",  folders    },
  60. X    { "merge",      merge_folders },
  61. X#ifdef CURSES
  62. X    { "curses",   curses_init },  { "bind",    bind_it    },
  63. X    { "unbind",   bind_it     },  { "bind-macro", bind_it  },
  64. X    { "unbind-macro", bind_it  },
  65. X#endif /* CURSES */
  66. X    { "map",      bind_it     },  { "unmap",       bind_it    },
  67. X    { "map!",     bind_it     },  { "unmap!",      bind_it    },
  68. X    { "preserve", preserve    },  { "unpreserve",  preserve   },
  69. X    { "replyall", respond     },  { "replysender", respond    },
  70. X    { "delete",      delete      },  { "undelete",    delete     },
  71. X    { "mail",       do_mail     },  { "echo",       do_echo    },
  72. X    { "lpr",      lpr          },  { "alternates",  alts       },
  73. X    { "edit",      edit_msg    },  { "flags",       msg_flags  },
  74. X    { "pipe",     pipe_msg    },  { "eval",       eval_cmd   },
  75. X    { "undigest", do_undigest    },
  76. X    { NULL, quit }
  77. X};
  78. X
  79. Xstruct cmd ucb_cmds[] = {
  80. X    { "t",   readmsg   }, { "n",  readmsg  }, { "p", readmsg  },
  81. X    { "+",   readmsg   }, { "-",  readmsg  }, { "P", readmsg  },
  82. X    { "Print", readmsg }, { "T",  readmsg  }, { "Type", readmsg },
  83. X    { "x",   quit      }, { "xit", quit    }, { "q",  quit    },
  84. X    { ":a",  do_hdrs   }, { ":d", do_hdrs  }, { ":r", do_hdrs },
  85. X    { ":o",  do_hdrs   }, { ":u", do_hdrs  }, { ":n", do_hdrs },
  86. X    { ":s",  do_hdrs   }, { ":p", do_hdrs  },
  87. X    { "z",   do_hdrs   }, { "z-", do_hdrs  }, { "z+", do_hdrs },
  88. X    { "h",   do_hdrs   }, { "H",  do_hdrs  },
  89. X    { "f",   do_from   }, { "m",  do_mail  }, { "alts", alts  },
  90. X    { "d",   delete    }, { "dt", delete   }, { "dp", delete  },
  91. X    { "u",   delete    }, { "fo", folder   },
  92. X    { "s",   save_msg  }, { "co", save_msg }, { "w", save_msg },
  93. X    { "pre", preserve  }, { "unpre", preserve },
  94. X    { "R",   respond   }, { "r",   respond },
  95. X    { "reply", respond }, { "respond", respond },
  96. X    { "v",   edit_msg  }, { "e",   edit_msg },
  97. X    { NULL, quit }
  98. X};
  99. X
  100. Xstruct cmd hidden_cmds[] = {
  101. X    { "debug", toggle_debug }, { "open",     nopenfiles },
  102. X    { "stty",    my_stty     },
  103. X    { "setenv",    Setenv      }, { "unsetenv",     Unsetenv   },
  104. X    { "printenv", Printenv  }, { "Pipe",    pipe_msg   },
  105. X    { NULL, quit }
  106. X};
  107. X
  108. Xtoggle_debug(argc, argv)
  109. Xchar **argv;
  110. X{
  111. X    if (argc < 2) /* no value -- toggle "debug" (off/on) */
  112. X    debug = !debug;
  113. X    else
  114. X    debug = atoi(*++argv);
  115. X    print("debugging value: %d\n", debug);
  116. X    return 0;
  117. X}
  118. X
  119. X/* if + was specified, then print messages without headers.
  120. X * n or \n (which will be NULL) will print next unread or undeleted message.
  121. X */
  122. Xreadmsg(x, argv, list)
  123. Xregister char **argv, list[];
  124. X{
  125. X    register char *p = x? *argv : NULL;
  126. X    register long flg = 0;
  127. X    extern FILE *ed_fp;
  128. X
  129. X    if (x && *++argv && !strcmp(*argv, "-?"))
  130. X    return help(0, "readmsg", cmd_help);
  131. X    /* View a message as long as user isn't in the editor.  If is_getting
  132. X     * is set, then the user is typing in a letter (or something else not
  133. X     * threatening in tool mode).  If ed_fp is not null, then we've got the
  134. X     * file open for typing.  If it's NULL, then an editor is going.
  135. X     */
  136. X    if (ison(glob_flags, IS_GETTING) && !ed_fp) {
  137. X    print("Not while you're in the editor, you don't.\n");
  138. X    return -1;
  139. X    }
  140. X    if (!msg_cnt) {
  141. X    print("No messages.\n");
  142. X    return -1;
  143. X    }
  144. X    if (x)
  145. X    if (!strcmp(p, "top"))
  146. X        turnon(flg, M_TOP);
  147. X    else if (*p == '+') {
  148. X        turnon(flg, NO_PAGE);
  149. X        turnon(flg, NO_HEADER);
  150. X    } else if (isupper(*p))
  151. X        turnon(flg, NO_IGNORE);
  152. X
  153. X    if (x && (x = get_msg_list(argv, list)) == -1)
  154. X    return -1;
  155. X    else if (x == 0) {  /* no arguments were parsed (or given) */
  156. X    /* get_msg_list sets current msg on */
  157. X    if (isoff(glob_flags, IS_PIPE))
  158. X        unset_msg_bit(list, current_msg);
  159. X    /* most commands move to the "next" message. type and print don't */
  160. X    if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
  161. X                    isoff(msg[current_msg].m_flags, UNREAD))
  162. X        current_msg++;
  163. X    if (p && (*p == '-' || !strcmp(p, "previous"))) {
  164. X        while (--current_msg >= 0 &&
  165. X        (ison(msg[current_msg].m_flags, DELETE) ||
  166. X         ison(msg[current_msg].m_flags, SAVED)))
  167. X        ;
  168. X        if (current_msg < 0) {
  169. X        print("No previous message.\n");
  170. X        current_msg = 0;
  171. X        return -1;
  172. X        }
  173. X    } else {
  174. X        /*
  175. X         * To be compatible with ucb-mail, find the next available unread
  176. X         * message.  If at the end, only wrap around if "wrap" is set.
  177. X         */
  178. X        if (current_msg == msg_cnt && do_set(set_options, "wrap"))
  179. X        current_msg = 0;
  180. X        /* "type" or "print" prints the current only -- "next" goes on.. */
  181. X        if (!p || !*p || *p == 'n')
  182. X        while (current_msg < msg_cnt &&
  183. X            (ison(msg[current_msg].m_flags, DELETE) ||
  184. X             ison(msg[current_msg].m_flags, SAVED)))
  185. X            current_msg++;
  186. X        if (current_msg >= msg_cnt) {
  187. X        print("No more messages.\n");
  188. X        current_msg = msg_cnt - 1;
  189. X        return -1;
  190. X        }
  191. X    }
  192. X    if (isoff(glob_flags, IS_PIPE))
  193. X        set_msg_bit(list, current_msg);
  194. X    }
  195. X    current_msg = 0;
  196. X    for (x = 0; x < msg_cnt; x++)
  197. X    if (msg_bit(list, x)) {
  198. X        current_msg = x;
  199. X#ifdef SUNTOOL
  200. X        if (istool > 1) {
  201. X        read_mail(NO_ITEM, 0, NO_EVENT);
  202. X        return 0;
  203. X        }
  204. X#endif /* SUNTOOL */
  205. X        display_msg(x, flg);
  206. X    }
  207. X    return 0;
  208. X}
  209. X
  210. Xpreserve(n, argv, list)
  211. Xregister int n;        /* no use for argc, so use space for a local variable */
  212. Xregister char **argv, list[];
  213. X{
  214. X    register int unpre;
  215. X
  216. X    unpre = !strncmp(*argv, "un", 2);
  217. X    if (*++argv && !strcmp(*argv, "-?"))
  218. X    return help(0, "preserve", cmd_help);
  219. X    if (get_msg_list(argv, list) == -1)
  220. X    return -1;
  221. X    for (n = 0; n < msg_cnt; n++)
  222. X    if (msg_bit(list, n))
  223. X        if (unpre) {
  224. X        if (ison(msg[n].m_flags, PRESERVE)) {
  225. X            turnoff(msg[n].m_flags, PRESERVE);
  226. X            turnon(glob_flags, DO_UPDATE);
  227. X        }
  228. X        } else {
  229. X        if (isoff(msg[n].m_flags, PRESERVE)) {
  230. X            /* || ison(msg[n].m_flags, DELETE)) */
  231. X            /* turnoff(msg[n].m_flags, DELETE); */
  232. X            turnon(msg[n].m_flags, PRESERVE);
  233. X            turnon(glob_flags, DO_UPDATE);
  234. X        }
  235. X        }
  236. X    if (istool)
  237. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  238. X    return 0;
  239. X}
  240. X
  241. Xlpr(n, argv, list)
  242. Xregister int n;  /* no use for argc, so use its address space for a variable */
  243. Xregister char **argv, list[];
  244. X{
  245. X    register FILE    *pp;
  246. X    register long     flags = 0;
  247. X    char        print_cmd[128], *printer, c, *cmd;
  248. X    int            total = 0;
  249. X    SIGRET        (*oldint)(), (*oldquit)();
  250. X
  251. X    turnon(flags, NO_IGNORE);
  252. X#ifdef MMDF
  253. X    turnon(flags, NO_SEPARATOR);
  254. X#endif /* MMDF */
  255. X    if (!(printer = do_set(set_options, "printer")) || !*printer)
  256. X    printer = DEF_PRINTER;
  257. X    while (argv && *++argv && **argv == '-') {
  258. X    n = 1;
  259. X    while (c = argv[0][n++])
  260. X        switch(c) {
  261. X        case 'n': turnon(flags, NO_HEADER);
  262. X        when 'h': turnoff(flags, NO_IGNORE);
  263. X        when 'P': case 'd':
  264. X            if (!argv[0][n]) {
  265. X                print("specify printer!\n");
  266. X                return -1;
  267. X            }
  268. X            printer = argv[0] + n;
  269. X            n += strlen(printer);
  270. X        otherwise: return help(0, "lpr", cmd_help);
  271. X        }
  272. X    }
  273. X    if (get_msg_list(argv, list) == -1)
  274. X    return -1;
  275. X
  276. X    if (cmd = do_set(set_options, "print_cmd"))
  277. X    (void) strcpy(print_cmd, cmd);
  278. X    else
  279. X#ifdef SYSV
  280. X    (void) sprintf(print_cmd, "%s -d%s", LPR, printer);
  281. X#else
  282. X    (void) sprintf(print_cmd, "%s -P%s", LPR, printer);
  283. X#endif /* SYSV */
  284. X    Debug("print command: %s\n", print_cmd);
  285. X    if (!(pp = popen(print_cmd, "w"))) {
  286. X    error("cannot print");
  287. X    return -1;
  288. X    }
  289. X    on_intr();
  290. X    for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
  291. X    if (msg_bit(list, n)) {
  292. X        if (total++)
  293. X        fputc('\f', pp); /* send a formfeed for multiple copies */
  294. X        print("printing message %d...", n+1);
  295. X        print_more("(%d lines)\n", copy_msg(n, pp, flags));
  296. X    }
  297. X    }
  298. X    off_intr();
  299. X    (void) pclose(pp);
  300. X    print_more("%d message%s printed ", total, (total==1)? "": "s");
  301. X    if (cmd)
  302. X    print_more("through \"%s\".\n", cmd);
  303. X    else
  304. X    print_more("at \"%s\".\n", printer);
  305. X    return 0;
  306. X}
  307. X
  308. X/* save [msg_list] [file] */
  309. Xsave_msg(n, argv, list)   /* argc isn't used, so use space for variable 'n' */
  310. Xregister char **argv, list[];
  311. X{
  312. X    register FILE    *mail_fp = NULL_FILE;
  313. X    register char     *file = NULL, *mode, firstchar = **argv, *tmp = ".";
  314. X    int         msg_number, force, by_subj = 0, by_author = 0;
  315. X    char        buf[MAXPATHLEN];
  316. X    long         flg = 0;
  317. X
  318. X    while (*++argv)
  319. X    if (*argv[0] != '-')
  320. X        break;
  321. X    else
  322. X        switch (argv[0][1]) {
  323. X        case 'S' :
  324. X            by_subj = 2;
  325. X        when 's' :
  326. X            by_subj = 1;
  327. X        when 'A' :
  328. X            by_author = 2;
  329. X        when 'a' :
  330. X            by_author = 1;
  331. X        otherwise :
  332. X            return help(0, "save", cmd_help);
  333. X        }
  334. X    if (force = (*argv && !strcmp(*argv, "!")))
  335. X    argv++;
  336. X    if ((n = get_msg_list(argv, list)) == -1)
  337. X    return -1;
  338. X    argv += n;
  339. X    if (*argv && *(file = *argv) == '\\')
  340. X    file++;
  341. X    else if (!file && !by_subj && !by_author) {
  342. X    /* if no filename specified, save in ~/mbox */
  343. X    if (firstchar == 'w') {
  344. X        /* mbox should have headers. If he really wants it, specify it */
  345. X        print("Must specify file name for 'w'\n");
  346. X        return -1;
  347. X    }
  348. X    if (!(file = do_set(set_options, "mbox")) || !*file)
  349. X        file = DEF_MBOX;
  350. X    }
  351. X    n = 1; /* tell getpath to ignore no such file or directory */
  352. X    if (file)
  353. X    tmp = getpath(file, &n);
  354. X    if (n < 0) {
  355. X    print("%s: %s\n", file, tmp);
  356. X    return -1;
  357. X    } else if (n && !by_subj && !by_author) {
  358. X    print("%s is a directory\n", file);
  359. X    return -1;
  360. X    }
  361. X    file = tmp;
  362. X    if (force || Access(file, F_OK))
  363. X    mode = "w", force = 0;
  364. X    else
  365. X    mode = "a";
  366. X    /*
  367. X     * open the file for writing (appending) unless we're saving by subject
  368. X     * or author name in which case we'll determine the filename later
  369. X     */
  370. X    if (!by_author && !by_subj && !(mail_fp = mask_fopen(file, mode))) {
  371. X    error("cannot save in \"%s\"", file);
  372. X    return -1;
  373. X    }
  374. X
  375. X#ifdef SUNTOOL
  376. X    if (istool)
  377. X    lock_cursors();
  378. X#endif /* SUNTOOL */
  379. X    turnon(flg, NO_IGNORE);
  380. X    if (firstchar == 'w') {
  381. X    turnon(flg, NO_HEADER);
  382. X#ifdef MMDF
  383. X    turnon(flg, NO_SEPARATOR);
  384. X#endif /* MMDF */
  385. X    } else
  386. X    turnon(flg, UPDATE_STATUS);
  387. X
  388. X    for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
  389. X    if (msg_bit(list, msg_number)) {
  390. X        if ((by_author || by_subj) && !mail_fp) {
  391. X        char buf2[256], addr[256];
  392. X        register char *p, *p2;
  393. X        if (by_subj) {
  394. X            if (p = header_field(msg_number, "subject")) {
  395. X            /* convert spaces and non-alpha-numerics to '_' */
  396. X            if (!lcase_strncmp(p, "re: ", 4))
  397. X                p += 4;
  398. X            for (p2 = p; *p2; p2++)
  399. X                if (!isalnum(*p2) && !index(".,@#$%-+=", *p2))
  400. X                *p2 = '_';
  401. X            } else
  402. X            p = "mbox";
  403. X        } else {
  404. X            (void) reply_to(msg_number, FALSE, buf2);
  405. X            (void) get_name_n_addr(buf2, NULL, addr);
  406. X            if (p = rindex(addr, '!'))
  407. X            p++;
  408. X            else
  409. X            p = addr;
  410. X            if (p2 = any(p, "@%"))
  411. X            *p2 = 0;
  412. X        }
  413. X        if (!p || !*p)
  414. X            p = "tmp";
  415. X        (void) sprintf(buf, "%s/%s", file, p);
  416. X        if (force || Access(buf, F_OK))
  417. X            mode = "w";
  418. X        else
  419. X            mode = "a";
  420. X        if (!(mail_fp = fopen(buf, mode))) {
  421. X            error("cannot save in \"%s\"", buf);
  422. X            if (by_author == 2 || by_subj == 2)
  423. X            break;
  424. X            continue;
  425. X        }
  426. X        }
  427. X            print("%sing msg %d ... ",
  428. X        (firstchar == 's')? "Sav" : "Writ", msg_number+1);
  429. X        print_more("(%d lines)", copy_msg(msg_number, mail_fp, flg));
  430. X        if (by_author == 1 || by_subj == 1) {
  431. X        print_more(" in \"%s\"", buf);
  432. X        fclose(mail_fp), mail_fp = NULL_FILE;
  433. X        }
  434. X        print_more("\n");
  435. X        n++;
  436. X        if (isoff(msg[msg_number].m_flags, SAVED) && firstchar != 'c') {
  437. X        turnon(glob_flags, DO_UPDATE);
  438. X        turnon(msg[msg_number].m_flags, SAVED);
  439. X        }
  440. X    }
  441. X    if (mail_fp) {
  442. X    fclose(mail_fp);
  443. X    if (!file)
  444. X        file = buf;
  445. X    print_more("%s %d msg%s to %s\n",
  446. X        (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
  447. X    }
  448. X#ifdef SUNTOOL
  449. X    if (istool) {
  450. X    unlock_cursors();
  451. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  452. X    add_folder_to_menu(folder_item, 3);
  453. X    add_folder_to_menu(save_item, 1);
  454. X    }
  455. X#endif /* SUNTOOL */
  456. X    return 0;
  457. X}
  458. X
  459. Xrespond(n, argv, list)
  460. Xregister int n;  /* no use for argc, so use its address space for a variable */
  461. Xregister char **argv, *list;
  462. X{
  463. X    register char *cmd = *argv;
  464. X    char list1[MAXMSGS_BITS];
  465. X    int cur_msg = current_msg;
  466. X
  467. X    if (*++argv && !strcmp(*argv, "-?"))
  468. X    return help(0, "respond", cmd_help);
  469. X    if ((n = get_msg_list(argv, list)) == -1)
  470. X    return -1;
  471. X
  472. X    /* make into our own list so ~: commands don't overwrite this list */
  473. X    bitput(list, list1, MAXMSGS, =);
  474. X
  475. X    /* back up one arg to replace "cmd" in the new argv[0] */
  476. X    argv += (n-1);
  477. X    if (!strcmp(cmd, "replyall"))
  478. X    Upper(*cmd);
  479. X    strdup(argv[0], cmd);
  480. X
  481. X    /* make sure the *current* message is the one being replied to */
  482. X    for (current_msg = -1, n = 0; n < msg_cnt && current_msg == -1; n++)
  483. X    if (msg_bit(list1, n) && current_msg == -1)
  484. X        current_msg = n;
  485. X    if (current_msg == -1) { /* "reply -" can cause this to happen */
  486. X    current_msg = cur_msg;
  487. X    return -1;
  488. X    }
  489. X    if (do_mail(1 /* ignored */, argv, list) == -1)
  490. X    return -1;
  491. X    for (n = 0; n < msg_cnt; n++)
  492. X    if (msg_bit(list1, n)) {
  493. X        /* set_isread(n); */
  494. X        set_replied(n); /* only if mail got delivered */
  495. X    }
  496. X    if (istool)
  497. X    do_hdrs(0, DUBL_NULL, NULL);
  498. X    /* copy the specified list back into msg_list */
  499. X    bitput(list1, list, MAXMSGS, =);
  500. X    return 0;
  501. X}
  502. X
  503. X/* cd to a particular directory specified by "p" */
  504. Xcd(x, argv) /* argc, unused -- use space for a non-register variable */
  505. Xregister char **argv;
  506. X{
  507. X    char cwd[MAXPATHLEN], buf[MAXPATHLEN];
  508. X    register char *path, *p = argv[1], *cdpath = NULL, *p2;
  509. X#ifdef SYSV
  510. X    char *getcwd();
  511. X#else
  512. X    char *getwd();
  513. X#endif /* SYSV */
  514. X    int err = 0;
  515. X
  516. X    if (!strcmp(*argv, "pwd") && (p = do_set(set_options, "cwd")) && *p) {
  517. X    print("%s\n", p);
  518. X    return -1;
  519. X    }
  520. X    if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
  521. X    p = (**argv == 'p')? "." : "~";
  522. X    /* if a full path was not specified, loop through cdpath */
  523. X    if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
  524. X    cdpath = do_set(set_options, "cdpath");
  525. X    do  {
  526. X    if (cdpath) {
  527. X        char c;
  528. X        if (p2 = any(cdpath, " \t:"))
  529. X        c = *p2, *p2 = 0;
  530. X        (void) sprintf(buf, "%s/%s", cdpath, p);
  531. X        if (cdpath = p2) /* assign and compare to NULL */
  532. X        *p2 = c;
  533. X        while (cdpath && isspace(*cdpath))
  534. X        cdpath++;
  535. X    } else
  536. X        (void) strcpy(buf, p);
  537. X    x = 0;
  538. X    path = getpath(buf, &x);
  539. X    if (x != 1 || chdir(path) == -1)
  540. X        err = errno;
  541. X    else
  542. X        err = 0;
  543. X    } while (err && cdpath && *cdpath);
  544. X    if (err)
  545. X    error(p);
  546. X#ifdef SYSV
  547. X    if (getcwd(cwd, sizeof cwd) == NULL)
  548. X#else
  549. X    if (getwd(cwd) == NULL)
  550. X#endif /* SYSV */
  551. X    print("can't get cwd: %s.\n", cwd), err++;
  552. X    else {
  553. X    char *new_argv[4];
  554. X    new_argv[0] = "cwd";
  555. X    new_argv[1] = "=";
  556. X    new_argv[2] = cwd;
  557. X    new_argv[3] = NULL;
  558. X    (void) add_option(&set_options, new_argv);
  559. X    }
  560. X    if (istool || iscurses || err) {
  561. X    if (err)
  562. X        turnon(glob_flags, CONT_PRNT);
  563. X    if (iscurses || istool || ison(glob_flags, WARNING))
  564. X        print("Working dir: %s\n", cwd);
  565. X    }
  566. X    return 0;
  567. X}
  568. X
  569. Xquit(argc, argv)
  570. Xchar **argv;
  571. X{
  572. X    u_long updated = ison(glob_flags, DO_UPDATE);
  573. X
  574. X    if (argc > 1 && !strcmp(argv[1], "-?"))
  575. X    return help(0, "quit", cmd_help);
  576. X    if ((!argc || (*argv && **argv == 'q')) && !copyback("Really Quit? "))
  577. X    return -1;
  578. X#ifdef CURSES
  579. X    if (iscurses) {
  580. X    /* we may already be on the bottom line; some cases won't be */
  581. X    move(LINES-1, 0), refresh();
  582. X    if (updated)
  583. X        putchar('\n');
  584. X    }
  585. X#endif /* CURSES */
  586. X    cleanup(0);
  587. X#ifdef lint
  588. X    return 0;
  589. X#endif /* lint */
  590. X}
  591. X
  592. Xdelete(argc, argv, list)
  593. Xregister int argc;
  594. Xregister char **argv, list[];
  595. X{
  596. X    register int prnt_next, undel = argc && **argv == 'u';
  597. X    int old_msg = current_msg;
  598. X
  599. X    prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
  600. X
  601. X    if (argc && *++argv && !strcmp(*argv, "-?")) {
  602. X    print("usage: delete/undelete [msg_list]\n");
  603. X    return -1;
  604. X    }
  605. X
  606. X    if (ison(glob_flags, READ_ONLY)) {
  607. X    print("Folder is read-only\n");
  608. X    return -1;
  609. X    }
  610. X
  611. X    if (get_msg_list(argv, list) == -1)
  612. X    return -1;
  613. X    for (argc = 0; argc < msg_cnt; argc++)
  614. X    if (msg_bit(list, argc))
  615. X        if (undel)
  616. X        turnoff(msg[argc].m_flags, DELETE);
  617. X        else
  618. X        turnon(msg[argc].m_flags, DELETE);
  619. X
  620. X    /* only if current_msg has been affected && not in curses mode */
  621. X    if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
  622. X    prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
  623. X
  624. X    turnon(glob_flags, DO_UPDATE);
  625. X
  626. X    /* goto next available message if current was just deleted.
  627. X     * If there are no more messages, turnoff prnt_next.
  628. X     */
  629. X    if (!iscurses && !undel && msg_bit(list, current_msg) &&
  630. X    (ison(msg[current_msg].m_flags, DELETE) ||
  631. X    ison(msg[current_msg].m_flags, SAVED)))
  632. X    next_msg();
  633. X
  634. X    if (prnt_next && !undel && !iscurses)
  635. X    if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
  636. X        display_msg(current_msg, (long)0);
  637. X    else
  638. X        print("No more messages.\n"), current_msg = old_msg;
  639. X#ifdef SUNTOOL
  640. X    if (istool)
  641. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  642. X#endif /* SUNTOOL */
  643. X    return 0;
  644. X}
  645. X
  646. X/*
  647. X * historically from the "from" command in ucb-mail, this just prints
  648. X * the composed header of the messages set in list or in pipe.
  649. X */
  650. Xdo_from(n, argv, list)
  651. Xchar **argv, list[];
  652. X{
  653. X    int inc_cur_msg = 0;
  654. X
  655. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  656. X    return help(0, "from", cmd_help);
  657. X    if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
  658. X    if (!strcmp(*argv, "+")) {
  659. X        if (!*++argv && current_msg < msg_cnt-1)
  660. X        current_msg++;
  661. X        inc_cur_msg = 1;
  662. X    } else if (!strcmp(*argv, "-")) {
  663. X        if (!*++argv && current_msg > 0)
  664. X        current_msg--;
  665. X        inc_cur_msg = -1;
  666. X    }
  667. X    if (get_msg_list(argv, list) == -1)
  668. X    return -1;
  669. X    for (n = 0; n < msg_cnt; n++)
  670. X    if (msg_bit(list, n)) {
  671. X        wprint("%s\n", compose_hdr(n));
  672. X        /* if -/+ given, set current message pointer to this message */
  673. X        if (inc_cur_msg) {
  674. X        current_msg = n;
  675. X        /* if - was given, then set to first listed message.
  676. X         * otherwise, + means last listed message -- let it go...
  677. X         */
  678. X        if (inc_cur_msg < 0)
  679. X            inc_cur_msg = 0;
  680. X        }
  681. X    }
  682. X    return 0;
  683. X}
  684. X
  685. X/*
  686. X * Do an ls from the system.
  687. X * Read from a popen and use wprint in case the tool does this command.
  688. X * The folders command uses this command.
  689. X */
  690. Xls(x, argv)
  691. Xchar **argv;
  692. X{
  693. X    register char  *p, *tmp;
  694. X    char       buf[128];
  695. X    register FILE  *pp;
  696. X
  697. X    if (*++argv && !strcmp(*argv, "-?"))
  698. X    return help(0, "ls", cmd_help);
  699. X    if (!(p = do_set(set_options, "lister")))
  700. X    p = "";
  701. X    (void) sprintf(buf, "%s -C%s ", LS_COMMAND, p);
  702. X    p = buf+strlen(buf);
  703. X    for ( ; *argv; ++argv) {
  704. X    x = 0;
  705. X    if (**argv != '-')
  706. X        tmp = getpath(*argv, &x);
  707. X    else
  708. X        tmp = *argv;
  709. X    if (x == -1) {
  710. X        wprint("%s: %s\n", *argv, tmp);
  711. X        return -1;
  712. X    }
  713. X    p += strlen(sprintf(p, " %s", tmp));
  714. X    }
  715. X    if (!(pp = popen(buf, "r"))) {
  716. X    error(buf);
  717. X    return -1;
  718. X    }
  719. X    (void) do_pager(NULL, TRUE);
  720. X    while (fgets(buf, 127, pp) && do_pager(buf, FALSE) != EOF)
  721. X    ;
  722. X    (void) pclose(pp);
  723. X    (void) do_pager(NULL, FALSE);
  724. X    return 0;
  725. X}
  726. X
  727. Xsh(un_used, argv)
  728. Xchar **argv;
  729. X{
  730. X    register char *p;
  731. X    char buf[128];
  732. X
  733. X    if (istool > 1 || *++argv && !strcmp(*argv, "-?"))
  734. X    return help(0, "shell", cmd_help);
  735. X    if (!(p = do_set(set_options, "shell"))
  736. X    && !(p = do_set(set_options, "SHELL")))
  737. X    p = DEF_SHELL;
  738. X    if (!*argv)
  739. X    (void) strcpy(buf, p);
  740. X    else
  741. X    (void) argv_to_string(buf, argv);
  742. X    echo_on();
  743. X    (void) system(buf);
  744. X    echo_off();
  745. X    return 0;
  746. X}
  747. X
  748. Xstatic
  749. Xsorter(cmd1, cmd2)
  750. Xregister struct cmd *cmd1, *cmd2;
  751. X{
  752. X    return strcmp(cmd1->command, cmd2->command);
  753. X}
  754. X
  755. Xquestion_mark(x, argv)
  756. Xchar **argv;
  757. X{
  758. X    int n = 0;
  759. X    char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, *malloc(), buf[30];
  760. X
  761. X    qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
  762. X            sizeof(struct cmd), sorter);
  763. X
  764. X    if (!*++argv) {
  765. X    for (x = 0; cmds[x].command; x++) {
  766. X        if (!(x % 5))
  767. X        if (!(p = Cmds[n++] = malloc(80))) {
  768. X            error("malloc in question_mark()");
  769. X            free_vec(Cmds);
  770. X            return -1;
  771. X        }
  772. X        p += strlen(sprintf(p, "%-14.14s ", cmds[x].command));
  773. X    }
  774. X    Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
  775. X    Cmds[n] = NULL;
  776. X    (void) help(0, Cmds, NULL);
  777. X    free_vec(Cmds);
  778. X    } else {
  779. X    for (x = 0; cmds[x].command; x++)
  780. X        if (!strcmp(*argv, cmds[x].command))
  781. X        return cmd_line(sprintf(buf, "\\%s -?", *argv), msg_list);
  782. X    print("Unknown command: %s\n", *argv);
  783. X    }
  784. X    return 0 - in_pipe();
  785. X}
  786. X
  787. X#ifdef SIGSTOP
  788. Xstop(argc, argv)
  789. Xchar **argv;
  790. X{
  791. X    if (istool)
  792. X    print("Not a tool-based option.");
  793. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  794. X    return help(0, "stop", cmd_help);
  795. X    if (kill(getpid(), SIGTSTP) == -1)
  796. X    error("couldn't stop myself");
  797. X    return 0;
  798. X}
  799. X#endif /* SIGSTOP */
  800. X
  801. Xextern char **environ;
  802. Xstatic int spaces = 0;
  803. X
  804. XSetenv(i, argv)
  805. Xchar **argv;
  806. X{
  807. X    char *newstr;
  808. X
  809. X    if (i < 2 || i > 3 || !strcmp(argv[1], "-?"))
  810. X    return help(0, "setenv", cmd_help);
  811. X
  812. X    if (i == 3) {
  813. X    newstr = malloc(strlen(argv[1]) + strlen(argv[2]) + 2);
  814. X    (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
  815. X    } else {
  816. X    newstr = malloc(strlen(argv[1]) + 2);
  817. X    (void) sprintf(newstr, "%s=", argv[1]);
  818. X    }
  819. X
  820. X    (void) Unsetenv(2, argv);
  821. X
  822. X    for (i = 0; environ[i]; i++);
  823. X    if (!spaces) {
  824. X    char **new_environ = (char **)malloc((i+2) * sizeof(char *));
  825. X    /* add 1 for the new item, and 1 for null-termination */
  826. X    if (!new_environ) {
  827. X        free(newstr);
  828. X        return -1;
  829. X    }
  830. X    spaces = 1;
  831. X    for (i = 0; new_environ[i] = environ[i]; i++);
  832. X    xfree(environ);
  833. X    environ = new_environ;
  834. X    }
  835. X    environ[i] = newstr;
  836. X    environ[i+1] = NULL;
  837. X    spaces--;
  838. X    return 0;
  839. X}
  840. X
  841. XUnsetenv(n, argv)
  842. Xchar **argv;
  843. X{
  844. X    char **envp, **last;
  845. X
  846. X    if (n != 2 || !strcmp(argv[1], "-?"))
  847. X    return help(0, "unsetenv", cmd_help);
  848. X
  849. X    n = strlen(argv[1]);
  850. X    for (last = environ; *last; last++);
  851. X    last--;
  852. X
  853. X    for (envp = environ; envp <= last; envp++) {
  854. X    if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
  855. X        xfree(*envp);
  856. X        *envp = *last;
  857. X        *last-- = NULL;
  858. X        spaces++;
  859. X    }
  860. X    }
  861. X    return 0;
  862. X}
  863. X
  864. XPrintenv(argc, argv)
  865. Xchar **argv;
  866. X{
  867. X    char **e;
  868. X    for (e = environ; *e; e++)
  869. X    if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
  870. X        wprint("%s\n", *e);
  871. X    return 0;
  872. X}
  873. X
  874. X/*
  875. X * internal stty call to allow the user to change his tty character
  876. X * settings.  sorry, no way to change cbreak/echo modes.  Save echo_flg
  877. X * so that execute() won't reset it.
  878. X */
  879. Xmy_stty(un_used, argv)
  880. Xchar **argv;
  881. X{
  882. X    u_long save_echo = ison(glob_flags, ECHO_FLAG);
  883. X
  884. X    turnon(glob_flags, ECHO_FLAG);
  885. X    execute(argv);
  886. X    if (save_echo)
  887. X    turnon(glob_flags, ECHO_FLAG);
  888. X    else
  889. X    turnoff(glob_flags, ECHO_FLAG);
  890. X
  891. X    savetty();
  892. X#ifdef TIOCGLTC
  893. X    if (ioctl(0, TIOCGLTC, <chars))
  894. X    error("TIOCGLTC");
  895. X#endif /* TIOCGLTC */
  896. X    echo_off();
  897. X    return 0;
  898. X}
  899. X
  900. X/*
  901. X * Edit a message...
  902. X */
  903. Xedit_msg(i, argv, list)
  904. Xchar *argv[], list[];
  905. X{
  906. X    int edited = 0;
  907. X    char buf[MAXPATHLEN], *dir, *edit_cmd[3];
  908. X    u_long flags = 0L;
  909. X    FILE *fp;
  910. X
  911. X    if (istool)
  912. X    return 0;
  913. X
  914. X    if (*++argv && !strcmp(*argv, "-?"))
  915. X    return help(0, "edit_msg", cmd_help);
  916. X
  917. X    if (ison(glob_flags, READ_ONLY)) {
  918. X    print("\"%s\" is read-only.\n", mailfile);
  919. X    return -1;
  920. X    }
  921. X
  922. X    if (get_msg_list(argv, list) == -1)
  923. X    return -1;
  924. X
  925. X    for (i = 0; i < msg_cnt; i++) {
  926. X    if (!msg_bit(list, i))
  927. X        continue;
  928. X
  929. X    if (edited) {
  930. X        print("Edit message %d [y/n/q]? ", i+1);
  931. X        if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
  932. X        return 0;
  933. X        if (buf[0] && buf[0] != 'y')
  934. X        continue;
  935. X    }
  936. X
  937. X    if (!(dir = do_set(set_options, "tmpdir")) &&
  938. X        !(dir = do_set(set_options, "home")))
  939. Xalted:
  940. X        dir = ALTERNATE_HOME;
  941. X    (void) mktemp(sprintf(buf, "%s/.msgXXXXXXX", dir));
  942. X    if (!(fp = mask_fopen(buf, "w+"))) {
  943. X        if (strcmp(dir, ALTERNATE_HOME))
  944. X        goto alted;
  945. X        error("can't create %s", buf);
  946. X        return -1;
  947. X    }
  948. X    wprint("editing message %d ...", i+1);
  949. X    /* copy message into file making sure all headers exist. */
  950. X    turnon(flags, UPDATE_STATUS);
  951. X#ifdef MMDF
  952. X    turnon(flags, NO_SEPARATOR);
  953. X#endif /* MMDF */
  954. X    wprint("(%d lines)\n", copy_msg(i, fp, flags));
  955. X
  956. X    if (!(edit_cmd[0] = do_set(set_options, "visual")) || !*edit_cmd[0])
  957. X        edit_cmd[0] = DEF_EDITOR;
  958. X    edit_cmd[1] = buf;
  959. X    edit_cmd[2] = NULL;
  960. X    print("Starting \"%s %s\"...\n", edit_cmd[0], buf);
  961. X    fclose(fp);
  962. X    turnon(glob_flags, IS_GETTING);
  963. X    execute(edit_cmd);
  964. X    turnoff(glob_flags, IS_GETTING);
  965. X    if (load_folder(buf, FALSE, (char *)i) > 0) {
  966. X        (void) unlink(buf);
  967. X        edited++;
  968. X    }
  969. X    set_isread(i); /* if you edit it, you read it, right? */
  970. X    }
  971. X    return 0;
  972. X}
  973. X
  974. X/*
  975. X * Pipe a message list to a unix command.  This function is hacked together
  976. X * from bits of readmsg, above, and other bits of display_msg (misc.c).
  977. X */
  978. Xpipe_msg(x, argv, list)
  979. Xregister char **argv, list[];
  980. X{
  981. X    char *p = x ? *argv : NULL;
  982. X    char buf[256];
  983. X    u_long flg = 0L;
  984. X    extern FILE *ed_fp;
  985. X
  986. X    /* Increment argv only if argv[0] is the mush command "pipe" */
  987. X    if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
  988. X    if (*++argv && !strcmp(*argv, "-?"))
  989. X        return help(0, "pipe_msg", cmd_help);
  990. X    else if (p && *p == 'P')
  991. X        turnon(flg, NO_HEADER);
  992. X    }
  993. X    /* Pipe a message as long as user isn't in the editor.  If is_getting
  994. X     * is set, then the user is typing in a letter (or something else not
  995. X     * threatening in tool mode).  If ed_fp is not null, then we've got the
  996. X     * file open for typing.  If it's NULL, then an editor is going.
  997. X     */
  998. X    if (ison(glob_flags, IS_GETTING) && !ed_fp) {
  999. X    print("Not while you're in the editor, you don't.\n");
  1000. X    return -1;
  1001. X    }
  1002. X    if (!msg_cnt) {
  1003. X    print("No messages.\n");
  1004. X    return -1;
  1005. X    }
  1006. X
  1007. X    if (x && (x = get_msg_list(argv, list)) == -1)
  1008. X    return -1;
  1009. X    else {
  1010. X    argv += x;
  1011. X    if (!*argv) {
  1012. X        print("No unix command for pipe!\n");
  1013. X        return -1;
  1014. X    }
  1015. X    (void) argv_to_string(buf, argv);
  1016. X    }
  1017. X    current_msg = 0;
  1018. X#ifdef MMDF
  1019. X    turnon(flg, NO_SEPARATOR);
  1020. X#endif /* MMDF */
  1021. X    (void) do_pager(buf, TRUE); /* start pager */
  1022. X    for (x = 0; x < msg_cnt; x++)
  1023. X    if (msg_bit(list, x)) {
  1024. X        current_msg = x;
  1025. X        if (ison(msg[x].m_flags, DELETE)) {
  1026. X        print("Message %d deleted; ", x+1);
  1027. X        if (iscurses)
  1028. X            print_more("skipping it.");
  1029. X        else
  1030. X            print("skipping it.\n");
  1031. X        continue;
  1032. X        }
  1033. X        set_isread(x);
  1034. X        (void) copy_msg(x, NULL_FILE, flg);
  1035. X    }
  1036. X    (void) do_pager(NULL, FALSE); /* end pager */
  1037. X    return 0;
  1038. X}
  1039. X
  1040. X/* echo the arguments.  return 0 or -1 if -h given and there are no msgs. */
  1041. Xdo_echo(n, argv)
  1042. Xregister char **argv;
  1043. X{
  1044. X    char buf[BUFSIZ], c;
  1045. X    int no_return = 0, comp_hdr = 0, as_prompt = 0;
  1046. X
  1047. X    while (argv && *++argv && **argv == '-') {
  1048. X    n = 1;
  1049. X    while (c = argv[0][n++])
  1050. X        switch(c) {
  1051. X        case 'n': no_return++;
  1052. X        when 'h': comp_hdr++;
  1053. X        when 'p': as_prompt++;
  1054. X        otherwise: return help(0, "echo", cmd_help);
  1055. X        }
  1056. X    }
  1057. X    if (comp_hdr && as_prompt) {
  1058. X    print("-h and -n cannot be used together.\n");
  1059. X    return -1;
  1060. X    }
  1061. X
  1062. X    (void) argv_to_string(buf, argv);
  1063. X    if (comp_hdr) {
  1064. X    char *save_hdr_fmt = hdr_format;
  1065. X    if (!msg_cnt) {
  1066. X        print("No messages.\n");
  1067. X        return -1;
  1068. X    }
  1069. X    hdr_format = buf;
  1070. X    print("%s", compose_hdr(current_msg)+9); /* there may be a %-sign */
  1071. X    hdr_format = save_hdr_fmt;
  1072. X    } else if (as_prompt) {
  1073. X    char *save_prompt = prompt;
  1074. X    prompt = buf;
  1075. X    mail_status(1);
  1076. X    prompt = save_prompt;
  1077. X    } else
  1078. X    print("%s", buf); /* there may be a %-sign in "buf" */
  1079. X    if (!no_return)
  1080. X    print_more("\n");
  1081. X    return 0;
  1082. X}
  1083. X
  1084. Xeval_cmd (argc, argv, list)
  1085. Xchar *argv[], list[];
  1086. X{
  1087. X    int status = -1;
  1088. X    u_long save_is_pipe;
  1089. X    char **newav, buf[BUFSIZ];
  1090. X
  1091. X    if (*++argv && !strcmp(*argv, "-?"))
  1092. X    return help(0, "eval", cmd_help);
  1093. X
  1094. X    (void) argv_to_string(buf,argv);
  1095. X    /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
  1096. X     * to remain on -- cmd_line() turns both of them off
  1097. X     */
  1098. X    if (newav = make_command(buf, TRPL_NULL, &argc)) {
  1099. X    save_is_pipe = ison(glob_flags, IS_PIPE);
  1100. X    status = do_command(argc, newav, list);
  1101. X    if (save_is_pipe)
  1102. X        turnon(glob_flags, IS_PIPE);
  1103. X    }
  1104. X    return status;
  1105. X}
  1106. END_OF_FILE
  1107. if test 29012 -ne `wc -c <'commands.c'`; then
  1108.     echo shar: \"'commands.c'\" unpacked with wrong size!
  1109. fi
  1110. # end of 'commands.c'
  1111. fi
  1112. echo shar: End of archive 13 \(of 19\).
  1113. cp /dev/null ark13isdone
  1114. MISSING=""
  1115. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1116.     if test ! -f ark${I}isdone ; then
  1117.     MISSING="${MISSING} ${I}"
  1118.     fi
  1119. done
  1120. if test "${MISSING}" = "" ; then
  1121.     echo You have unpacked all 19 archives.
  1122.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1123. else
  1124.     echo You still need to unpack the following archives:
  1125.     echo "        " ${MISSING}
  1126. fi
  1127. ##  End of shell archive.
  1128. exit 0
  1129.